/*
 * REFTimer.cpp
 *
 *  Created on: Jun 12, 2013
 *      Author: Lucifer
 */

#include "../pch.h"
#include "events.h"
#include "REFTimerService.h"

namespace BFX
{

/**
 * Initializes a new instance of the BFX::REFTimer with given dispatcher.
 * @param pDispatcher The event dispatcher.
 */
REFTimer::REFTimer(REFEventDispatcher* pDispatcher)
{
	Initialize(Time::MinValue(), pDispatcher);
}

/**
 * Initializes a new instance of the BFX::REFTimer with given absolute expiration, dispatcher.
 * @param absoluteExpiration The absolute expiration.
 * @param pDispatcher the event dispatcher.
 */
REFTimer::REFTimer(const Time& absoluteExpiration, REFEventDispatcher* pDispatcher)
{
	Initialize(absoluteExpiration, pDispatcher);
}

/**
 * Initializes a new instance of the BFX::REFTimer with given sliding expiration, dispatcher.
 * @param slidingExpiration The sliding expiration.
 * @param pDispatcher The event dispatcher.
 */
REFTimer::REFTimer(const TimeSpan& slidingExpiration, REFEventDispatcher* pDispatcher)
{
	Initialize(Time::Now() + slidingExpiration, pDispatcher);
}

void REFTimer::Initialize(const Time& absoluteExpiration, REFEventDispatcher* pDispatcher)
{
	BFX_REQUIRE(pDispatcher != NULL);

	m_pContextQueue = new REFTimerContextQueue();
	m_nSortIndex = 0;
	m_pPrev = m_pNext = NULL;

	m_pTimerService = pDispatcher->GetServiceRegistry()->CreateOrGetService<REFTimerService>();
	SetAbsoluteExpiration(absoluteExpiration);
}

/**
 * Destructor to destroys the BFX::REFTimer instance.
 */
REFTimer::~REFTimer()
{
	Cancel();
	m_pTimerService = NULL;
}

/**
 * Gets the timer's absolute expiration time.
 * @return
 */
Time REFTimer::GetAbsoluteExpiration() const
{
	return m_absoluteExpiration;
}

/**
 * Sets the timer's absolute expiration time.
 * @param absoluteExpiration
 */
void REFTimer::SetAbsoluteExpiration(const Time& absoluteExpiration)
{
	Cancel();
	m_absoluteExpiration = absoluteExpiration;
}

/**
 * Gets the timer's sliding expiration time from now.
 * @return
 */
TimeSpan REFTimer::GetSlidingExpiration() const
{
	return m_absoluteExpiration.ToUtcTime() - Time::UtcNow();
}

/**
 * Sets the timer's sliding expiration time from now.
 * @param slidingExpiration
 */
void REFTimer::SetSlidingExpiration(const TimeSpan& slidingExpiration)
{
	SetAbsoluteExpiration(Time::Now() + slidingExpiration);
}

/**
 * Performs a blocking wait on the timer.
 */
void REFTimer::Wait()
{
	// TODO:
}

/**
 * Starts an asynchronous wait on the timer.
 * @param callback
 */
void REFTimer::WaitAsync(TimerCallback callback)
{
	m_pTimerService->WaitAsync(this, callback);
}

/**
 * Cancel all asynchronous operations that are waiting on the timer.
 * @return The number of asynchronous operations that were canceled.
 */
int REFTimer::Cancel()
{
	return m_pTimerService->Cancel(this);
}

} /* namespace BFX */
